package com.easipass.framework.eirframeworkcoredsl;

public class TransitionNode extends AstNode {

    public final static String FAIL = "$FAIL";

    public final static String END = "$END";

    private Token statusToken;

    private String status;

    private boolean isExitCodeCheck;

    private Token targetLabel;

    private ServiceNode targetService;

    private TransitionNode(Token statusToken, int endPos) {
        super(statusToken.startPos, endPos);
        this.statusToken = statusToken;
        if (statusToken.isKind(TokenKind.LITERAL_STRING)) {
            isExitCodeCheck = false;
            String quotesUsed = statusToken.data.substring(0, 1);
            this.status = statusToken.data.substring(1, statusToken.data.length() - 1).replace(quotesUsed + quotesUsed,
                    quotesUsed);
        } else {
            isExitCodeCheck = true;
            if (statusToken.isKind(TokenKind.STAR)) {
                this.status = "*";
            } else {
                this.status = this.statusToken.stringValue();
            }
        }
    }

    static TransitionNode toLabelReference(Token transitionOnToken, Token labelReference) {
        TransitionNode t = new TransitionNode(transitionOnToken, labelReference.endPos);
        t.targetLabel = labelReference;
        return t;
    }

    static TransitionNode toAnotherService(Token transitionOnToken, ServiceNode targetService) {
        TransitionNode t = new TransitionNode(transitionOnToken, targetService.endPos);
        t.targetService = targetService;
        return t;
    }

    @Override
    public String stringify(boolean includePositionInfo) {
        StringBuilder s = new StringBuilder();
        s.append(" ");
        s.append(statusToken.getKind() == TokenKind.STAR ? "*" : statusToken.stringValue()).append("->");
        if (targetLabel != null) {
            s.append(":").append(targetLabel.stringValue());
        } else {
            s.append(targetService.stringify(includePositionInfo));
        }
        return s.toString();
    }

    public String getStatusToCheck() {
        return status;
    }

    public String getStatusToCheckInDSLForm() {
        if (isExitCodeCheck) {
            return status;
        } else {
            return "'" + status + "'";
        }
    }

    public boolean isTargetService() {
        return targetService != null;
    }

    public String getTargetLabel() {
        return targetLabel == null ? null : targetLabel.stringValue();
    }

    public ServiceNode getTargetService() {
        return targetService;
    }

    public boolean isSpecialTransition() {
        return isFailTransition() || isEndTransition();
    }

    public boolean isFailTransition() {
        return getTargetService().getName().equals(FAIL);
    }

    public boolean isEndTransition() {
        return getTargetService().getName().equals(END);
    }

    public boolean isExitCodeCheck() {
        return isExitCodeCheck;
    }

    public String getTargetDslText() {
        if (targetLabel == null) {
            return targetService.toDslText();
        } else {
            return ":" + targetLabel.stringValue();
        }
    }

    public void accept(Visitor visitor) {
        boolean cont = visitor.preVisit(this);
        if (!cont) {
            return;
        }
        visitor.visit(this);
        visitor.postVisit(this);
    }
}
